package com.hj.quartz.common.job;


import com.hj.common.util.StringUtils;
import com.hj.common.util.spring.SpringUtils;
import com.hj.quartz.common.pojo.entity.JobQuartz;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.LinkedList;
import java.util.List;

/**
 * 任务执行调用类 : 运用反射实现调用类方法
 */
public class JobInvoke {

    /**
     * 执行调用该方法
     *
     * @param jobQuartz
     */
    public static void invokeMethod(JobQuartz jobQuartz) throws Exception {
        String beanClass = jobQuartz.getBeanClass();//获取执行方法  类名 + 方法名
        String beanName = getBeanName(beanClass);//获取类名
        String methodName = getMethodName(beanClass);//获取方法名
        List<Object[]> methodParams = getMethodParams(beanClass);//获取参数列表

        //获取spring的bean对象
        Object bean = SpringUtils.getBean(beanName);
        invokeMethod(bean, methodName, methodParams);
    }

    /**
     * 调用任务方法 : 反射调用方法
     *
     * @param bean         目标对象
     * @param methodName   方法名称
     * @param methodParams 方法参数
     */
    private static void invokeMethod(Object bean, String methodName, List<Object[]> methodParams)
            throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException,
            InvocationTargetException {
        //判断方法是否有参数
        if (StringUtils.isNotNull(methodParams) && methodParams.size() > 0) {
            //反射调用带参构造
            Method method = bean.getClass().getDeclaredMethod(methodName, getMethodParamsType(methodParams));
            method.invoke(bean, getMethodParamsValue(methodParams));
        } else {
            //反射调用无参构造
            Method method = bean.getClass().getDeclaredMethod(methodName);
            method.invoke(bean);
        }
    }

    /**
     * 获取类名
     *
     * @param beanClass 目标字符串  eg : user.isAdmin()   user.class.isAdmin()
     * @return bean名称
     */
    public static String getBeanName(String beanClass) {
        //从 "." 最后一次出现的位置向前截取
        return StringUtils.substringBeforeLast(beanClass, ".");
    }

    /**
     * 获取方法名
     *
     * @param beanClass 目标字符串  eg : user.isAdmin()
     * @return method方法
     */
    public static String getMethodName(String beanClass) {
        String methodName = StringUtils.substringBefore(beanClass, "(");
        //从 "." 最后一次出现的位置向后截取
        return StringUtils.substringAfterLast(methodName, ".");
    }

    /**
     * 获取method方法参数相关列表
     *
     * @param beanClass 目标字符串  eg : user.isAdmin('flag',flag2,flag3)  如果参数是String类型则用 ''
     * @return method方法相关参数列表
     */
    public static List<Object[]> getMethodParams(String beanClass) {
        //获取目标方法参数
        String methodStr = StringUtils.substringBetween(beanClass, "(", ")");
        if (StringUtils.isEmpty(methodStr)) {
            return null;
        }
        //获取参数数组
        String[] methodParams = methodStr.split(",");
        List<Object[]> classs = new LinkedList<>();
        for (int i = 0; i < methodParams.length; i++) {
            //字符串不为null时去除字符串头尾的空串返回
            String str = StringUtils.trimToEmpty(methodParams[i]);
            // String字符串类型，包含'
            if (StringUtils.contains(str, "'")) {
                //把参数里的 ' 替换为 空串
                classs.add(new Object[]{StringUtils.replace(str, "'", ""), String.class});
            }
            // boolean布尔类型，等于true或者false
            else if (StringUtils.equals(str, "true") || StringUtils.equalsIgnoreCase(str, "false")) {
                classs.add(new Object[]{Boolean.valueOf(str), Boolean.class});
            }
            // long长整形，包含L
            else if (StringUtils.containsIgnoreCase(str, "L")) {
                classs.add(new Object[]{Long.valueOf(StringUtils.replaceIgnoreCase(str, "L", "")), Long.class});
            }
            // double浮点类型，包含D
            else if (StringUtils.containsIgnoreCase(str, "D")) {
                classs.add(new Object[]{Double.valueOf(StringUtils.replaceIgnoreCase(str, "D", "")), Double.class});
            }
            // 其他类型归类为整形
            else {
                classs.add(new Object[]{Integer.valueOf(str), Integer.class});
            }
        }
        return classs;
    }

    /**
     * 获取参数类型
     *
     * @param methodParams 参数相关列表
     * @return 参数类型列表
     */
    public static Class<?>[] getMethodParamsType(List<Object[]> methodParams) {
        Class<?>[] classs = new Class<?>[methodParams.size()];
        int index = 0;
        for (Object[] os : methodParams) {
            classs[index] = (Class<?>) os[1];
            index++;
        }
        return classs;
    }

    /**
     * 获取参数值
     *
     * @param methodParams 参数相关列表
     * @return 参数值列表
     */
    public static Object[] getMethodParamsValue(List<Object[]> methodParams) {
        Object[] classs = new Object[methodParams.size()];
        int index = 0;
        for (Object[] os : methodParams) {
            classs[index] = (Object) os[0];
            index++;
        }
        return classs;
    }
}
